﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using System.Web;
using HCQ2_Common;
using HCQ2_DAL_MSSQL;
using HCQ2_DI;
using HCQ2_IBLL;
using HCQ2_IDAL;
using HCQ2_Model;
using HCQ2_Model.ClassRoom;
using HCQ2_Model.Data;
using HCQ2_Model.ViewModel;

namespace HCQ2_BLL
{
    /// <summary>
    /// 直播课堂
    /// </summary>
    public partial class N_VRLineClassRoomBLL : IN_VRLineClassRoomBLL
    {
        #region 数据库操作

        /// <summary>
        /// 直播课堂数据库操作
        /// </summary>
        private IN_VRLineClassRoomDAL ClassRoomDAL {
            get {
                return DBSession.IN_VRLineClassRoomDAL;
            }
        }
        /// <summary>
        /// 直播课堂-课件关联表数据库操作
        /// </summary>
        private IN_VRLineClassRoomFileDAL ClassRoomFileDAL {
            get {
                return DBSession.IN_VRLineClassRoomFileDAL;
            }
        }
        /// <summary>
        /// 直播课堂-学生上课数据库操作
        /// </summary>
        private IN_VRUserAttendDAL UserAttendDAL {
            get {
                return DBSession.IN_VRUserAttendDAL;
            }
        }

        #endregion


        public OperationResult<int?> Create(ClassRoomCreateDto dto)
        {
            return Write(dto,
                ()=>{ 
                    return CheckRoomTime(CurrentInfo.GetUserId(), dto.StartTime.Value, dto.StartLen.Value);
                },
                ()=>{
                N_VRLineClassRoom room = dto.ThisMapTo();
                room.EndTime = room.StartTime.AddMinutes(room.StartLen);
                room.UserName = CurrentInfo.GetLoginName();
                room.UserId = CurrentInfo.GetUserId();
                room.UserName = CurrentInfo.GetLoginName();
                room.CreateId = CurrentInfo.GetUserId();
                room.CreateName = CurrentInfo.GetUserName();
                room.CreateDate = DateTime.Now;
                room.UpdateId = CurrentInfo.GetUserId();
                room.UpdateName = CurrentInfo.GetLoginName();
                room.UpdateDate = DateTime.Now;

                ClassRoomDAL.Add(room);

                //课堂创建成功后使用ID创建课件关联信息
                dto.FileInfo.ForEach(o => {
                    N_VRLineClassRoomFile roomFile = o.MapTo<N_VRLineClassRoomFile>();
                    roomFile.RmId = room.RmId;
                    roomFile.CreateId = CurrentInfo.GetUserId();
                    roomFile.CreateDate = DateTime.Now;
                    ClassRoomFileDAL.Add(roomFile);
                });
                return new OperationResult<int?>(true, $"创建直播课堂【{dto.CrName}】成功",room.RmId);
            });
        }

        public OperationResult<int?> Update(ClassRoomUpdateDto dto)
        {
            var classRoom = ClassRoomFileDAL.FindSingle(w => w.RmId == dto.RmId.Value);
            if (classRoom == null) {
                return new OperationResult<int?>(false, $"直播课堂不存在，请检查ID");
            }

            return Write(dto,
                ()=>{ 
                    return CheckRoomTime(CurrentInfo.GetUserId(), dto.StartTime.Value, dto.StartLen.Value, dto.RmId);
                },
                () => {
                    using (TransactionScope transaction = new TransactionScope())
                    {
                        //删除原本课件
                        ClassRoomFileDAL.Delete(w => w.RmId == dto.RmId);
                        //修改信息
                        N_VRLineClassRoom room = dto.ThisMapTo();
                        room.EndTime = room.StartTime.AddMinutes(room.StartLen);
                        room.UpdateId = CurrentInfo.GetUserId();
                        room.UpdateName = CurrentInfo.GetLoginName();
                        room.UpdateDate = DateTime.Now;
                        ClassRoomDAL.Modify(room, w => w.RmId == dto.RmId, "FolderId", "FolderPath", "CrName", "StartTime", "StartLen", "EndTime", "Scope", "IP", "Price", "PersonNumber", "IfFinish", "VideoUrl", "Note", "UpdateId", "UpdateName", "UpdateDate", "Device");
                        //课堂修改成功后使用ID创建课件关联信息
                        dto.FileInfo.ForEach(o => {
                            N_VRLineClassRoomFile roomFile = o.MapTo<N_VRLineClassRoomFile>();
                            roomFile.RmId = room.RmId;
                            roomFile.CreateId = CurrentInfo.GetUserId();
                            roomFile.CreateDate = DateTime.Now;
                            ClassRoomFileDAL.Add(roomFile);
                        });

                        transaction.Complete();
                    }
                    return new OperationResult<int?>(true, $"修改直播课堂【{dto.CrName}】成功");
                });
        }

        public OperationResult Delete(ClassRoomDeleteDto dto)
        {
            var classRoom = ClassRoomDAL.FindSingle(d => d.RmId == dto.id.Value);
            if (classRoom == null)
            {
                return new OperationResult(false, "未找到直播课堂");
            }

            using (TransactionScope transaction = new TransactionScope())
            {
                ClassRoomDAL.Delete(d => d.RmId == dto.id.Value);
                ClassRoomFileDAL.Delete(w => w.RmId == dto.id.Value);
                UserAttendDAL.Delete(w => w.RmId == dto.id.Value);

                transaction.Complete();
            }

            return new OperationResult(true, "删除直播课堂成功");
        }

        public OperationResult<TableModel<List<ClassRoomQueryResultDto>>> List(ClassRoomQueryDto dto)
        {
            if (!string.IsNullOrEmpty(dto.CreateUserId))
            {
                T_User user = DBSession.IT_UserDAL.FindSingle(ww => ww.user_guid.Equals(dto.CreateUserId));
                if (user == null)
                {
                    return new OperationResult<TableModel<List<ClassRoomQueryResultDto>>>(false, "通过CreateUserId未找到对应的用户信息，请检查");                    
                }
                dto.CreateUserId = user.user_id.ToString();
            }
            

            var result = ClassRoomDAL.List(dto);
            if (result == null) {
                return new OperationResult<TableModel<List<ClassRoomQueryResultDto>>>(true, "获取数据成功", null);
            }

            result.rows.ForEach((c) => {
                if (!string.IsNullOrEmpty(c.FolderImgUrl)) {
                    c.FolderImgUrl = c.FolderImgUrl.Replace("~", HttpContext.Current.Request.Url.AbsoluteUri.Substring(0, HttpContext.Current.Request.Url.AbsoluteUri.IndexOf("/api/")));
                }

                c.RoomFiles.ForEach((f) => {
                    if (!string.IsNullOrEmpty(f.FileImgUrl)) { 
                        f.FileImgUrl = f.FileImgUrl.Replace("~", HttpContext.Current.Request.Url.AbsoluteUri.Substring(0, HttpContext.Current.Request.Url.AbsoluteUri.IndexOf("/api/")));
                    }
                });

                if (!string.IsNullOrEmpty(c.CreateNamePhotoUrl)) {
                    c.CreateNamePhotoUrl = c.CreateNamePhotoUrl.Replace("~", HttpContext.Current.Request.Url.AbsoluteUri.Substring(0, HttpContext.Current.Request.Url.AbsoluteUri.IndexOf("/api/")));
                }

            });

            return new OperationResult<TableModel<List<ClassRoomQueryResultDto>>>(true,"获取数据成功", result);
        }
        
        public OperationResult SaveUserInfo(ClassRoomSaveUserInfoDto dto)
        {
            var classRoom = ClassRoomDAL.FindSingle(w => w.RmId == dto.RmId);
            if (classRoom == null) {
                return new OperationResult(false,"未找到对应的直播课堂信息");
            }

            var student = DBSession.IT_UserDAL.FindSingle(w => w.user_guid.Equals(dto.userid));
            if (student == null) {
                return new OperationResult(false,"未找到对应的用户信息");
            }

            var classRoomCheck = ClassRoomDAL.FindSingle(w => w.RmId == dto.RmId.Value && w.UserId == CurrentInfo.GetUserId());
            if (classRoomCheck != null) {
                return new OperationResult(false, "用户已经添加了课堂不用再次添加");
            }

            N_VRUserAttend userAttend = dto.ThisMapTo();
            userAttend.UserId = CurrentInfo.GetUserId();
            userAttend.CreateId = CurrentInfo.GetUserId();
            userAttend.CreateDate = DateTime.Now;
            userAttend.LearnDate = DateTime.Now;
            userAttend.UserGuid = student.user_guid;
            UserAttendDAL.Add(userAttend);

            return new OperationResult(true, "保存成功");
        }
        
        public OperationResult SaveVideo(ClassRoomSaveVideoDto dto)
        {
            var classRoom = ClassRoomDAL.FindSingle(w => w.RmId == dto.RmId);
            if (classRoom == null)
            {
                return new OperationResult(false, "未找到对应的直播课堂信息");
            }

            N_VRLineClassRoom classRoom1 = new N_VRLineClassRoom();
            classRoom1.IfFinish = dto.IfFinish.Value;
            classRoom1.VideoUrl = dto.VideoUrl;
            classRoom1.UpdateDate = DateTime.Now;
            classRoom1.UpdateId = CurrentInfo.GetUserId();
            classRoom1.UpdateName = CurrentInfo.GetLoginName();

            ClassRoomDAL.Modify(classRoom1,w => w.RmId==dto.RmId, "VideoUrl", "IfFinish", "UpdateId", "UpdateName", "UpdateDate");

            return new OperationResult(true,"保存成功");
        }
        
        public OperationResult<int> GetClassRoomPersonNumber(GetClassRoomPersonNumberQueryDto dto)
        {
            int val = ClassRoomDAL.GetClassRoomPersonNumber(dto);

            return new OperationResult<int>(true,"获取数据成功",val);
        }
        
        public OperationResult<int> GetClassRoomNumber(GetClassRoomNumberQueryDto dto)
        {
            int val = ClassRoomDAL.GetClassRoomNumber(dto);

            return new OperationResult<int>(true, "获取数据成功",val);
        }


        #region 私有的方法
        /// <summary>
        /// 检查用户在一个时间段是否已经存在有直播记录
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="dateTime">时间</param>
        /// <param name="StartLen">时长，但是：分钟</param>
        /// <param name="rmId">直播课堂ID，新增为空</param>
        /// <returns></returns>
        private string CheckRoomTime(int userId,DateTime dateTime,int StartLen, int? rmId=null)
        {
            var classRooms = ClassRoomDAL.CheckClassRoomTimeOverlap(userId,dateTime,dateTime.AddMinutes(StartLen));
            if (classRooms == null || classRooms.Count == 0) {
                return null;
            }

            if (rmId != null)
            {
                //获取重叠记录中是否存在更新的数据
                var updateInfo = classRooms.FirstOrDefault(w => w.RmId == rmId.Value);
                //重叠记录中包含update数据
                if (updateInfo != null)
                {
                    //删除更新数据的重叠
                    classRooms.Remove(updateInfo);
                }

                if (classRooms.Count == 0)
                {
                    return null;
                }
            }

            List<string> sb = new List<string>(classRooms.Count);
            classRooms.ForEach((r) => {
                sb.Add($"课堂名称：{r.CrName}，上课时间：{r.StartTime.ToString("yyyy-MM-dd HH:mm")}，时长：{r.StartLen}分钟");
            });

            return string.Join(",",sb);
        }

        /// <summary>
        /// 检查目录是否存在
        /// </summary>
        /// <param name="folderId"></param>
        /// <returns></returns>
        private bool CheckFolder(int folderId)
        {
            var folder = DBSession.IT_DocumentFolderDAL.FindSingle(w=>w.folder_id==folderId);
            if (folder == null) {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 检查课件是否存在
        /// </summary>
        /// <param name="fileId"></param>
        /// <returns></returns>
        private bool CheckFile(int fileId)
        {
            var file = DBSession.IT_DocumentInfoDAL.FindSingle(w=>w.file_id==fileId);
            if (file == null) {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 创建和修改直播课堂
        /// </summary>
        /// <param name="dto">创建和修改直播课堂的DTO参数</param>
        /// <param name="beforeValid">创建和修改，上课时间冲突验证</param>
        /// <param name="operation">创建和修改，相同验证后不同的处理</param>
        /// <returns></returns>
        /// <remarks>创建和修改开始的校验有一样</remarks>
        private OperationResult<int?> Write(ClassRoomCreateDto dto,Func<string> beforeValid,Func<OperationResult<int?>> operation)
        {
            //同一个用户（老师）在同一个时间段只能存在一个直播课堂（已删除的除外）
            string valid = beforeValid();
            if (!string.IsNullOrEmpty(valid))
            {
                return new OperationResult<int?>(false, $"课堂上课时间和存在的直播课堂上课时间存在冲突，冲突信息：{valid}");
            }

            if (!CheckFolder(dto.FolderId.Value))
            {
                return new OperationResult<int?>(false, "找不到对应的目录");
            }

            if (dto.FileInfo == null || dto.FileInfo.Count == 0)
            {
                return new OperationResult<int?>(false, "至少需要一个课件");
            }

            List<int> fileErr = new List<int>();
            dto.FileInfo.ForEach(o => {
                if (!CheckFile(o.FileId.Value))
                    fileErr.Add(o.FileId.Value);
            });
            if (fileErr.Count > 0)
            {
                return new OperationResult<int?>(false, $"课件id找不到对应课件，id：{string.Join(",", fileErr)}");
            }

            return operation();
        }
        #endregion

    }
}
